package tools.blat;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;

public class overlap2 {
    
    private static Vector gene = new Vector();
    private static Vector ncrna = new Vector();
    private static Vector eOverlap = new Vector();
    private static Vector iOverlap = new Vector();
    
    private static Vector inExons = new Vector();
    
    private static int geneSpan = 8;
    private static int exonSpan = 4;

    public static void pslToVector(String file, Vector v) throws Exception{
	int count=0;
	try{	
	    BufferedReader reader= new BufferedReader(new FileReader(file));
	    PslParser parser= new PslParser(reader);
	    EstAlignment a = null;
	    while (parser.hasNext()) {
		a = (EstAlignment)parser.next();
		v.add(a);
		if((count++ % 100) == 0)
		    System.out.println (count);
	    }
	} catch(FileNotFoundException fnfe){
	    System.out.println("Error reading file: "+fnfe);
	    fnfe.printStackTrace();
	} catch(Exception e){
	    System.out.println("Error : "+e);
	    e.printStackTrace();
	} 
    }
    
    public static boolean overLap(EstAlignment a, EstAlignment b, int span) {
	int aStart;
	int aEnd;
	int bStart;
	int bEnd;
	boolean overLap = false;

	if(a.tname.equalsIgnoreCase(b.tname)   && (a.strand[0] == b.strand[0] || a.strand[0] != b.strand[0])){ //  && a.strand[0] != b.strand[0]  ) { //  check for overlap if a and b are on the same chromo
	    aStart = (int) a.tstart;
	    aEnd = (int) a.tend;
	   
	    bStart = (int) b.tstart;
	    bEnd = (int) b.tend;
	    
	    overLap = over(aStart, aEnd, bStart, bEnd, span);
	    
	}
	return overLap; // true if they overlap else false
    }

    public static boolean over(int aStart, int aEnd, int bStart, int bEnd, int span) {
	boolean overLap = false;
	
	if(aStart <= bStart && aEnd <= bEnd && (aEnd-bStart) >= span)
	    overLap = true;
	else if (aStart >= bStart && aEnd >= bEnd && (bEnd-aStart) >= span)
	    overLap = true;
	else if (aStart <= bStart && aEnd >= bEnd)
	    overLap = true;
	else if (aStart >= bStart && aEnd <= bEnd)
	    overLap = true;

	return overLap;
    }
    
    public static void eOverlap(){
	EstAlignment g = null;
	EstAlignment n = null;
	
	for(int i=0;i<ncrna.size();i++){ //iterates over rna
	    n = (EstAlignment) ncrna.elementAt(i);
	    for(int j=0;j<gene.size();j++){ // iterates over est
		g = (EstAlignment) gene.elementAt(j);
		
		if(overLap(n, g, geneSpan) && exonOverLap(n, g, exonSpan)) //  
		    eOverlap.add(n.qname+"\t"+g.qname+"\n");
		
	    }
	}
    }

    
    
    public static boolean exonOverLap(EstAlignment a, EstAlignment b, int span) {
	boolean over = false;
	for (int i=0; i<a.tStarts.length; i++) {
	    for (int j=0; j<b.tStarts.length; j++) {
		if(over(a.tStarts[i], a.tStarts[i]+a.blockSizes[i],b.tStarts[j], b.tStarts[j]+b.blockSizes[j], span)) {
			over = true; 
			break;
		}
		
	    }
		if(over)
		    break;
	}
	return over;
    }

    
    /*
    public static boolean exonOverLap(EstAlignment a, EstAlignment b, int span) {
	boolean over = false;
	for (int i=0; i<a.tStarts.length; i++) {
	    for (int j=0; j<b.tStarts.length; j++) {
		if((j==0 || j==b.tStarts.length-1)  && over(a.tStarts[i], a.tStarts[i]+a.blockSizes[i],b.tStarts[j], b.tStarts[j]+b.blockSizes[j], span)) {
			over = true; 
			break;
		}
		
	    }
		if(over)
		    break;
	}
	return over;
    }
    */

    public static void inExon() {
	EstAlignment g = null;
	EstAlignment n = null;
	
	for(int i=0; i<ncrna.size();i++){
	    n = (EstAlignment) ncrna.elementAt(i);
	    for(int j=0;j<gene.size();j++){
		g = (EstAlignment) gene.elementAt(j);

		if(g.tname.equalsIgnoreCase(n.tname) && g.strand[0] == n.strand[0]  && isInExon(n, g)) {
		    //inExons.add(g.qname+"\t"+n.qname+"\n");
		    int gsize = g.tend-g.tstart;
		    int nsize = n.tend-n.tstart;
		    
		    if(gsize>=nsize)
			inExons.add(g.qname+"\t"+n.qname+"\n");
		    else
			inExons.add(n.qname+"\t"+g.qname+"\n");

		    
		}
	    }
	}
    }

    public static boolean isInExon(EstAlignment a, EstAlignment b) {
	boolean in = false;
	for (int i=0; i<b.tStarts.length; i++) {
	    if(a.tstart>=b.tStarts[i] && a.tend <=b.tStarts[i]+b.blockSizes[i]) {
		in = true;
		break;
	    }
	}
	return in;
    }
		    
    
    public static void intronOverlap() {
	EstAlignment g = null;
	EstAlignment n = null; 
	
	for(int i=0; i<gene.size(); i++) {
	    g = (EstAlignment) gene.elementAt(i);
	   
	    for(int j=0; j<ncrna.size(); j++) {
		n = (EstAlignment) ncrna.elementAt(j);

		for(int z=0; z<g.tStarts.length-1; z++) {
		    if( (g.tname.equals(n.tname))  && (g.strand[0] == n.strand[0]) &&  ((g.tStarts[z]+g.blockSizes[z]) <= n.tstart) && ((g.tStarts[z+1]) >= n.tend)) { //  
			iOverlap.add(g.qname+"\t"+n.qname+"\t"+(z+1)+ "\t"+ n.qStarts.length +"\t["+g.tStarts[z]+g.blockSizes[z]+"->"+n.tstart+"->"+n.tend+"->"+g.tStarts[z+1]+"]"+ "\n");
			break;
		    }
		}
	    }
	}
    }


     private static void vectorToTxtFile(Vector v, String fileName){
	try{
	    FileWriter fw = new FileWriter(fileName);
	    BufferedWriter bw = new BufferedWriter(fw);
	    for(int i=0;i<v.size();i++){
		bw.write( (String)v.elementAt(i));
	    }
	    bw.close();
	} catch(IOException ioe){
	    System.out.println(ioe);
	    ioe.printStackTrace();
	}
    }


     public static void main (String[] args) throws IOException, InterruptedException {
	if(args.length != 4){
	    System.out.println("Wrong number of parameters!" + '\n' + "Usage: overlap [exon|intron|all] path/fileDir path/file1.psl path/file2.psl");
	    System.out.println("Infiles may contain genes, ests, ncRNA etc. (in psl format!)");

	    System.exit(0);
	}
	String type = args[0];
	if(!type.equalsIgnoreCase("exon") && !type.equalsIgnoreCase("intron") && !type.equalsIgnoreCase("all") && !type.equalsIgnoreCase("inExon")) {
	    System.out.println("Wrong type!" + '\n' + "Type must be [exon|intron|all]");
	    System.out.println(type);
	    System.exit(0);
	}

	String dir = args[1];
	String ncFile = args[2];
	String geneFile = args[3];
	String eOutFile = dir+"exon_overlap.txt";
	String iOutFile = dir+"intron_overlap.txt";
	String inExonFile = dir+"in_exon_overlap.txt";
	
	System.out.print("---READING ncRNA FILE--- ");
	try {
	    pslToVector(ncFile, ncrna);
	} catch (Exception e) {}
	System.out.println("OK");
	
	System.out.print("---READING EST FILE--- ");
	try {
	    pslToVector(geneFile, gene);
	} catch (Exception e) {}
	System.out.println("OK");     
	
	System.out.println("---MATCHING "+type+" OVERLAP---");
	if(type.equalsIgnoreCase("exon") || type.equalsIgnoreCase("all") ) {
	    eOverlap();
	    vectorToTxtFile( eOverlap, eOutFile);
	}
	if(type.equalsIgnoreCase("intron") || type.equalsIgnoreCase("all")) {
	    intronOverlap();
	    vectorToTxtFile( iOverlap, iOutFile);
	}
	
	if(type.equalsIgnoreCase("inExon")) {
	    inExon();
	    vectorToTxtFile( inExons, inExonFile);
	}

	System.out.println("DONE!");
     }
}
